ひとりNavigation API Advent Calendar 24日目
https://gyazo.com/6fcdab63e97f318c2514d9aac6b9c035
これはひとりNavigation API Advent Calendarの24日目です。
ページ遷移で関連しそうなView Transitions APIについて触れていきます
そもそもView Transitions APIとは何か
ページ遷移時にトランジションアニメーションをつけ、遷移に対して効果的な切り替えができるようになるWeb API
Reactだと<ViewTransition>、Vue Routerだと<transition>コンポーネントがあってその内部でトランジション効果をつけられるようになっていたりする
Vue Routerサンプル:https://vue-portfolio.yamanoku.net/
こうした処理はルーターライブラリで実現していたのをWeb API、つまりJavaScriptとCSSだけで実現できるようになる
2025年にNewly Baselineになりました
https://gyazo.com/2e4d72ea5d19c29d576fc814444cf5ea
今年のInterop 2025の対象にもなっています
WPT
https://wpt.fyi/results/css/css-view-transitions?label=master&label=experimental&aligned&view=interop&q=label%3Ainterop-2025-view-transitions
ひとりNavigation API Advent Calendar 14日目で作ったNavigation APIのクライアントサイドルーティングにView Transitions APIを足してみます
ソースコード:https://codepen.io/yamanoku/pen/xbOxPPW
協力:Gemini 3 Pro
https://scrapbox.io/files/694b83a399c35468d46d76db.mov
変更点
intercept()内にstartViewTransitionを指定する
code:js
// View Transitions API がサポートされている場合
if (document.startViewTransition) {
const transition = document.startViewTransition(() => {
this.handleRoute(url.pathname);
});
await transition.finished;
} else {
// サポートされていない場合は即座に更新
this.handleRoute(url.pathname);
}
ページの戻る・進む押下時の判定処理を入れる
code:js
let lastIndex = navigation.currentEntry.index;
navigation.addEventListener('currententrychange', (event) => {
const currentIndex = navigation.currentEntry.index;
if (currentIndex < lastIndex) { // 戻るを押下したとき
document.documentElement.dataset.direction = 'back';
} else if (currentIndex > lastIndex) { // 進むを押下したとき
document.documentElement.dataset.direction = 'forward';
}
lastIndex = currentIndex;
});
コンテンツ領域のみがアニメーションするように指定
code:css
#app {
padding: 2rem;
view-transition-name: page-content; /* コンテンツ領域のみがアニメーションするように指定 */
}
View Transitions APIのアニメーション指定
code:css
/* --- View Transitions API Animations --- */
::view-transition-old(page-content),
::view-transition-new(page-content) {
animation-duration: 0.4s;
animation-timing-function: ease-in-out;
animation-fill-mode: both;
mix-blend-mode: normal; /* 重要: ページが透けて重なるのを防ぐ */
}
:rootdata-direction="forward"::view-transition-old(page-content) {
animation-name: slide-out-to-left;
}
:rootdata-direction="forward"::view-transition-new(page-content) {
animation-name: slide-in-from-right;
}
:rootdata-direction="back"::view-transition-old(page-content) {
animation-name: slide-out-to-right;
z-index: 1;
}
:rootdata-direction="back"::view-transition-new(page-content) {
animation-name: slide-in-from-left;
z-index: 2;
}
/* キーフレーム定義 */
@keyframes slide-out-to-left {
from { transform: translateX(0); }
to { transform: translateX(-100%); }
}
@keyframes slide-in-from-right {
from { transform: translateX(100%); }
to { transform: translateX(0); }
}
@keyframes slide-out-to-right {
from { transform: translateX(0); }
to { transform: translateX(100%); }
}
@keyframes slide-in-from-left {
from { transform: translateX(-100%); }
to { transform: translateX(0); }
}
参考記事
仕様
CSS View Transitions Module Level 1
CSS View Transitions Module Level 2
シングルページ アプリケーションのビュー遷移 | web.dev
View Transition API によるスムーズな遷移 | View Transitions | Chrome for Developers
https://view-transitions.chrome.dev/pagination/spa-types/
View Transitions API と Navigation API でページ遷移アニメーションを実装してみる